from django.db import models
from django.contrib.auth.models import AbstractUser, Group, Permission
from django.db import models

class User(AbstractUser):
    ROLE_CHOICES = (
        ('superadmin', '超级管理员'),
        ('admin', '管理员'),
        ('operator', '操作员'),
    )
    role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='operator', verbose_name='角色')
    managed_projects = models.ManyToManyField('Project', blank=True, verbose_name='管理项目')
    phone = models.CharField(max_length=20, blank=True, verbose_name='联系电话')
    department = models.CharField(max_length=100, blank=True, verbose_name='部门')
    
    groups = models.ManyToManyField(
        Group,
        verbose_name='groups',
        blank=True,
        help_text='The groups this user belongs to.',
        related_name='myapp_user_set',
        related_query_name='user',
    )
    user_permissions = models.ManyToManyField(
        Permission,
        verbose_name='user permissions',
        blank=True,
        help_text='Specific permissions for this user.',
        related_name='myapp_user_set',
        related_query_name='user',
    )
    
    class Meta:
        verbose_name = '用户'
        verbose_name_plural = '用户'
    
    def __str__(self):
        return f"{self.username} ({self.get_role_display()})"

class Project(models.Model):
    name = models.CharField(max_length=100, verbose_name='工程名称')
    code = models.CharField(max_length=50, unique=True, verbose_name='工程编号')
    location = models.CharField(max_length=200, verbose_name='工程位置')
    start_date = models.DateField(verbose_name='开始日期')
    end_date = models.DateField(null=True, blank=True, verbose_name='结束日期')
    description = models.TextField(blank=True, verbose_name='工程描述')
    zones = models.JSONField(default=list, verbose_name='监测区域划分', blank=True)
    monitoring_areas = models.JSONField(default=list, verbose_name='监测区域划分', blank=True, help_text='JSON格式存储各监测区域信息，包含区域名称、边界坐标、监测点分组等')
    zone_details = models.JSONField(default=dict, verbose_name='区域详细信息')
    project_manager = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='项目负责人')
    
    def __str__(self):
        return self.name

class Building(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE, verbose_name='所属工程')
    name = models.CharField(max_length=100, verbose_name='建筑物名称')
    location = models.CharField(max_length=200, verbose_name='建筑物位置')
    section = models.CharField(max_length=50, verbose_name='监测断面')
    section_details = models.JSONField(default=dict, verbose_name='断面详细信息', null=True)
    monitoring_points = models.JSONField(default=list, verbose_name='监测点信息', null=True)
    monitoring_sections = models.JSONField(default=list, verbose_name='监测断面信息')
    section_groups = models.JSONField(default=list, verbose_name='断面分组信息')
    building_type = models.CharField(max_length=50, verbose_name='建筑物类型', blank=True)
    construction_date = models.DateField(null=True, blank=True, verbose_name='建设日期')
    
    def __str__(self):
        return f"{self.name} ({self.project})"

class News(models.Model):
    CATEGORY_CHOICES = (
        ('progress', '工程进展'),
        ('api', 'API信息'),
        ('conference', '会议展示'),
    )
    
    title = models.CharField(max_length=200, verbose_name='标题')
    content = models.TextField(verbose_name='内容')
    category = models.CharField(max_length=20, choices=CATEGORY_CHOICES, verbose_name='分类')
    publish_date = models.DateTimeField(auto_now_add=True, verbose_name='发布时间')
    is_published = models.BooleanField(default=True, verbose_name='是否发布')
    
    def __str__(self):
        return self.title

class Announcement(models.Model):
    CATEGORY_CHOICES = (
        ('alert', '公众预警'),
        ('progress', '工程进展'),
        ('api', 'API信息'),
        ('conference', '会议展示'),
    )
    
    title = models.CharField(max_length=200, verbose_name='标题')
    content = models.TextField(verbose_name='内容')
    category = models.CharField(max_length=20, choices=CATEGORY_CHOICES, verbose_name='分类')
    publish_date = models.DateTimeField(auto_now_add=True, verbose_name='发布时间')
    is_published = models.BooleanField(default=True, verbose_name='是否发布')
    
    def __str__(self):
        return self.title

class Sensor(models.Model):
    SENSOR_STATUS = (
        ('normal', '正常'),
        ('warning', '预警'),
        ('offline', '离线'),
    )
    
    SENSOR_TYPES = (
        ('water_level', '水位计'),
        ('seepage', '渗压计'),
        ('crack', '测缝计'),
        ('fracture', '裂缝计'),
        ('displacement', '位移计'),
        ('temperature', '温度计'),
        ('pressure', '压力计'),
        ('inclinometer', '倾角计'),
    )
    
    SENSOR_SPECS = {
        'water_level': {
            'measurement_unit': '米',
            'range': '0-50',
            'precision': '±0.01',
            'notes': '水位测量传感器，适用于水库、河流等水位监测',
            'typical_application': '水库大坝、河流堤防、湖泊监测',
            'installation_notes': '需垂直安装，避免水流冲击'
        },
        'seepage': {
            'measurement_unit': '千帕',
            'range': '0-1000',
            'precision': '±0.1',
            'notes': '渗压测量传感器，用于监测大坝、堤防等渗流压力',
            'typical_application': '大坝基础、地下工程、边坡监测',
            'installation_notes': '需埋设在渗流关键部位'
        },
        'crack': {
            'measurement_unit': '毫米',
            'range': '0-100',
            'precision': '±0.05',
            'notes': '裂缝测量传感器，用于监测建筑物裂缝变化',
            'typical_application': '混凝土结构、桥梁、隧道',
            'installation_notes': '需跨裂缝安装，两端固定牢固'
        },
        'displacement': {
            'measurement_unit': '毫米',
            'range': '0-500',
            'precision': '±0.1',
            'notes': '位移测量传感器，用于监测建筑物位移变化',
            'typical_application': '边坡、基坑、大坝变形监测',
            'installation_notes': '需固定基准点，避免振动干扰'
        },
        'temperature': {
            'measurement_unit': '摄氏度',
            'range': '-40-80',
            'precision': '±0.5',
            'notes': '温度测量传感器，用于环境温度监测',
            'typical_application': '混凝土温度、环境温度监测',
            'installation_notes': '避免阳光直射和热源干扰'
        },
        'pressure': {
            'measurement_unit': '千帕',
            'range': '0-10000',
            'precision': '±1',
            'notes': '压力测量传感器，用于结构压力监测',
            'typical_application': '支护结构、桩基、隧道衬砌',
            'installation_notes': '需与受力面紧密接触'
        },
        'inclinometer': {
            'measurement_unit': '度',
            'range': '0-90',
            'precision': '±0.1',
            'notes': '倾角测量传感器，用于建筑物倾斜度监测',
            'typical_application': '高耸结构、边坡、挡土墙',
            'installation_notes': '需固定安装，避免振动干扰'
        }
    }
    
    building = models.ForeignKey(Building, on_delete=models.CASCADE, verbose_name='所属建筑物')
    name = models.CharField(max_length=100, verbose_name='传感器名称')
    location = models.CharField(max_length=100, verbose_name='安装位置')
    status = models.CharField(max_length=10, choices=SENSOR_STATUS, default='normal', verbose_name='状态')
    sensor_type = models.CharField(max_length=50, choices=SENSOR_TYPES, verbose_name='传感器类型')
    installation_date = models.DateField(verbose_name='安装日期')
    
    design_code = models.CharField(max_length=50, blank=True, null=True, default='未指定', verbose_name='设计编号')
    latitude = models.FloatField(verbose_name='纬度', null=True, blank=True)
    longitude = models.FloatField(verbose_name='经度', null=True, blank=True)
    alarm_threshold = models.JSONField(default=dict, blank=True, null=True, verbose_name='告警阈值')
    management_unit = models.CharField(max_length=100, blank=True, null=True, default='未指定', verbose_name='管理单位')
    gateway = models.CharField(max_length=100, blank=True, null=True, default='未指定', verbose_name='所连网关')
    port_number = models.CharField(max_length=20, blank=True, null=True, default='未指定', verbose_name='端口号')
    last_maintenance = models.DateField(null=True, blank=True, verbose_name='上次维护日期')
    notes = models.TextField(blank=True, verbose_name='备注')
    manufacturer = models.CharField(max_length=100, blank=True, verbose_name='生产厂家')
    model_number = models.CharField(max_length=50, blank=True, verbose_name='型号')
    measurement_range = models.CharField(max_length=100, blank=True, verbose_name='量程')
    accuracy = models.CharField(max_length=50, blank=True, verbose_name='精度')
    sampling_rate = models.CharField(max_length=50, blank=True, verbose_name='采样频率')
    
    def get_sensor_specs(self):
        return self.SENSOR_SPECS.get(self.sensor_type, {})
    
    def __str__(self):
        return f"{self.name} ({self.get_status_display()})"

class MonitoringData(models.Model):
    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE, verbose_name='传感器')
    timestamp = models.DateTimeField(auto_now_add=True, verbose_name='时间戳')
    stress = models.FloatField(verbose_name='应力值')
    displacement = models.FloatField(verbose_name='位移值')
    seepage = models.FloatField(verbose_name='渗流值')
    temperature = models.FloatField(verbose_name='温度值')
    pressure = models.FloatField(verbose_name='压力值')
    tilt = models.FloatField(verbose_name='倾斜度')
    is_abnormal = models.BooleanField(default=False, verbose_name='是否异常')
    
    class Meta:
        ordering = ['-timestamp']
        verbose_name = '监测数据'
        verbose_name_plural = '监测数据'
    
    def __str__(self):
        return f"{self.sensor.name} - {self.timestamp}"

class AlertRule(models.Model):
    name = models.CharField(max_length=100, verbose_name='规则名称')
    parameter = models.CharField(max_length=50, verbose_name='监测参数')
    threshold = models.FloatField(verbose_name='阈值')
    severity = models.CharField(max_length=20, verbose_name='严重程度')
    is_active = models.BooleanField(default=True, verbose_name='是否启用')
    
    class Meta:
        verbose_name = '告警规则'
        verbose_name_plural = '告警规则'
    
    def __str__(self):
        return f"{self.name} ({self.parameter} > {self.threshold})"

class AlertLog(models.Model):
    SEVERITY_CHOICES = (
        ('critical', '严重'),
        ('warning', '警告'),
        ('info', '信息'),
    )
    
    STATUS_CHOICES = (
        ('pending', '待处理'),
        ('processing', '处理中'),
        ('resolved', '已解决'),
        ('false_alarm', '误报'),
    )
    
    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE, verbose_name='传感器')
    rule = models.ForeignKey(AlertRule, on_delete=models.CASCADE, verbose_name='触发规则')
    timestamp = models.DateTimeField(auto_now_add=True, verbose_name='时间戳')
    severity = models.CharField(max_length=20, choices=SEVERITY_CHOICES, verbose_name='严重程度')
    value = models.FloatField(verbose_name='监测值')
    is_resolved = models.BooleanField(default=False, verbose_name='是否已解决')
    resolved_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='解决人')
    resolved_at = models.DateTimeField(null=True, blank=True, verbose_name='解决时间')
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending', verbose_name='处理状态')
    notes = models.TextField(blank=True, null=True, verbose_name='处理备注')
    
    class Meta:
        ordering = ['-timestamp']
        verbose_name = '告警日志'
        verbose_name_plural = '告警日志'
    
    def __str__(self):
        return f"{self.sensor.name} - {self.rule.name} ({self.get_severity_display()})"

class SystemLog(models.Model):
    LOG_TYPE_CHOICES = (
        ('login', '登录日志'),
        ('system', '系统日志'),
        ('operation', '操作日志'),
    )
    
    user = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='用户')
    log_type = models.CharField(max_length=20, choices=LOG_TYPE_CHOICES, verbose_name='日志类型')
    timestamp = models.DateTimeField(auto_now_add=True, verbose_name='时间戳')
    ip_address = models.GenericIPAddressField(verbose_name='IP地址')
    action = models.CharField(max_length=200, verbose_name='操作内容')
    details = models.TextField(blank=True, verbose_name='详细信息')
    
    class Meta:
        ordering = ['-timestamp']
        verbose_name = '系统日志'
        verbose_name_plural = '系统日志'
    
    def __str__(self):
        return f"{self.get_log_type_display()} - {self.action}"



class Feedback(models.Model):
    name = models.CharField(max_length=100, verbose_name='姓名')
    contact = models.CharField(max_length=100, verbose_name='联系方式')
    content = models.TextField(verbose_name='反馈内容')
    timestamp = models.DateTimeField(auto_now_add=True, verbose_name='提交时间')
    is_processed = models.BooleanField(default=False, verbose_name='是否处理')
    
    class Meta:
        ordering = ['-timestamp']
        verbose_name = '意见反馈'
        verbose_name_plural = '意见反馈'
    
    def __str__(self):
        return f"{self.name} - {self.content[:50]}"

class Gateway(models.Model):
    name = models.CharField(max_length=100, verbose_name='网关名称')
    ip_address = models.GenericIPAddressField(verbose_name='IP地址')
    mac_address = models.CharField(max_length=50, verbose_name='MAC地址')
    location = models.CharField(max_length=100, verbose_name='安装位置')
    status = models.CharField(max_length=20, default='active', verbose_name='状态')
    last_heartbeat = models.DateTimeField(null=True, blank=True, verbose_name='最后心跳时间')
    firmware_version = models.CharField(max_length=50, verbose_name='固件版本')
    notes = models.TextField(blank=True, verbose_name='备注')
    manufacturer = models.CharField(max_length=100, blank=True, verbose_name='生产厂家')
    model_number = models.CharField(max_length=50, blank=True, verbose_name='型号')
    measurement_range = models.CharField(max_length=100, blank=True, verbose_name='量程')
    accuracy = models.CharField(max_length=50, blank=True, verbose_name='精度')
    sampling_rate = models.CharField(max_length=50, blank=True, verbose_name='采样频率')
    
    class Meta:
        verbose_name = '网关'
        verbose_name_plural = '网关'
    
    def __str__(self):
        return self.name

class Calibration(models.Model):
    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE, verbose_name='传感器')
    calibration_date = models.DateField(verbose_name='校准日期')
    calibrated_by = models.CharField(max_length=100, verbose_name='校准人员')
    next_calibration_date = models.DateField(verbose_name='下次校准日期')
    calibration_method = models.CharField(max_length=200, blank=True, verbose_name='校准方法')
    calibration_result = models.JSONField(default=dict, verbose_name='校准结果')
    notes = models.TextField(blank=True, verbose_name='备注')
    
    def __str__(self):
        return f"{self.sensor.name} - {self.calibration_date}"
    
    class Meta:
        verbose_name = '传感器校准'
        verbose_name_plural = '传感器校准'

class SystemConfig(models.Model):
    key = models.CharField(max_length=100, unique=True, verbose_name='配置键')
    value = models.TextField(verbose_name='配置值')
    description = models.TextField(blank=True, verbose_name='描述')
    is_secret = models.BooleanField(default=False, verbose_name='是否敏感')
    
    class Meta:
        verbose_name = '系统配置'
        verbose_name_plural = '系统配置'
    
    def __str__(self):
        return self.key

class DataPoint(models.Model):
    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE, verbose_name='传感器')
    timestamp = models.DateTimeField(auto_now_add=True, verbose_name='时间戳')
    value = models.FloatField(verbose_name='监测值')
    
    class Meta:
        verbose_name = '数据点'
        verbose_name_plural = '数据点'
        ordering = ['-timestamp']
    
    def __str__(self):
        return f"{self.sensor.name} - {self.timestamp}"

class Alert(models.Model):
    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE, verbose_name='传感器')
    alert_type = models.CharField(max_length=50, verbose_name='告警类型')
    alert_time = models.DateTimeField(auto_now_add=True, verbose_name='告警时间')
    message = models.TextField(verbose_name='告警信息')
    is_resolved = models.BooleanField(default=False, verbose_name='是否解决')
    resolved_by = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='解决人')
    resolved_at = models.DateTimeField(null=True, blank=True, verbose_name='解决时间')
    
    class Meta:
        verbose_name = '告警'
        verbose_name_plural = '告警'
        ordering = ['-alert_time']
    
    def __str__(self):
        return f"{self.sensor.name} - {self.alert_type}"
